using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Globalization;

namespace ResourceBlender_Express.Validators {
    /// <summary>
    /// Validates a string
    /// </summary>
    public class StringValidationRule : ValidationRule {
        private int minLength = -1;
        private int maxLength = -1;
        private string errorMessage = string.Empty;
        private bool enabled = true;

        /// <summary>
        /// Gets or sets the minimum length. Default is no minimum length.
        /// </summary>
        /// <value>The minimum length.</value>
        public int MinimumLength {
            get { return minLength; }
            set { minLength = value; }
        }

        /// <summary>
        /// Gets or sets the maximum length. Default is no maximum length.
        /// </summary>
        /// <value>The maximum length.</value>
        public int MaximumLength {
            get { return maxLength; }
            set { maxLength = value; }
        }

        /// <summary>
        /// Gets or sets the error message returned if the string is invalid.
        /// </summary>
        /// <value>The error message.</value>
        public string ErrorMessage {
            get { return errorMessage; }
            set { errorMessage = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this validator is enabled (default is <c>true</c>).
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this validator is enabled, otherwise <c>false</c>.
        /// </value>
        public bool IsEnabled {
            get { return enabled; }
            set { enabled = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="StringValidationRule"/> class.
        /// </summary>
        public StringValidationRule() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="StringValidationRule"/> class.
        /// </summary>
        /// <param name="minLength">Length of the min.</param>
        /// <param name="maxLength">Length of the max.</param>
        /// <param name="errorMessage">The error message.</param>
        public StringValidationRule(int minLength, int maxLength, string errorMessage) {
            this.minLength = minLength;
            this.maxLength = maxLength;
            this.errorMessage = errorMessage;
        }

        /// <summary>
        /// Performs a validation check on a value.
        /// </summary>
        /// <param name="value">The value from the binding target to check.</param>
        /// <param name="cultureInfo">The culture to use in this rule.</param>
        /// <returns>
        /// A <see cref="T:System.Windows.Controls.ValidationResult"/> object.
        /// </returns>
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) {
            ValidationResult result = new ValidationResult(true, null);
            string inputString = (value ?? string.Empty).ToString();
            if(inputString.Length <= this.MinimumLength || (this.MaximumLength > 0 && inputString.Length > this.MaximumLength)) {
                result = new ValidationResult(false, this.ErrorMessage);
            }
            return result;
        }
    }

    /// <summary>
    /// Validates an integer falls within a given range.
    /// </summary>
    public class IntegerRangeValidationRule : ValidationRule {
        private int min = int.MinValue,
                    max = int.MaxValue;

        private string errorMessage = null;
        private bool isGeneric = false;

        /// <summary>
        /// Gets or sets the minimum value.
        /// </summary>
        public int MinValue {
            get { return min; }
            set { min = value; }
        }

        /// <summary>
        /// Gets or sets the maximum value.
        /// </summary>
        public int MaxValue {
            get { return max; }
            set { max = value; }
        }

        /// <summary>
        /// Gets or sets the message to display on invalid data.
        /// </summary>
        /// <value>The error message.</value>
        public string ErrorMessage {
            get { return errorMessage; }
            set { errorMessage = value; }
        }

        /// <summary>
        /// Gets or sets whether this comparer will just require an integer or require an integer between two values.
        /// </summary>
        /// <value>The is generic.</value>
        public bool IsGeneric {
            get { return isGeneric; }
            set { isGeneric = value; }
        }

        /// <summary>
        /// Performs a validation check on a value.
        /// </summary>
        /// <param name="value">The value from the binding target to check.</param>
        /// <param name="cultureInfo">The culture to use for this rule.</param>
        /// <returns>A <see cref="ValidationResult"/> object representing the result of the validation.</returns>
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) {
            int parsedValue;
            string message = null;
            if(string.IsNullOrEmpty((string)value)) {
                message = "You must enter an integer.";
            } else if(!int.TryParse((string)value, NumberStyles.Integer, cultureInfo.NumberFormat, out parsedValue)) {
                message = "You must enter an integer.";
            } else if(parsedValue < MinValue || parsedValue > MaxValue) {
                message = string.Format("Value must be between {0} and {1}", MinValue, MaxValue);
            }
            if(message != null) {
                if(isGeneric || ErrorMessage == null) {
                    return new ValidationResult(false, message);
                } else {
                    return new ValidationResult(false, errorMessage);
                }
            } else {
                return new ValidationResult(true, null);
            }
        }
    }
}
